Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BREAKING(http/unstable): add capability to attach handlers by methods, implement sensible defaults #6305

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

kerezsiz42
Copy link

Hi everyone!

I would like to propose a new implementation of the route() function that adds the capability to define handlers on a per-method basis (in a style similar to Fresh) or to use a single handler that handles all methods.

I envision the route() function being used only once when we pass it to Deno.serve(). In the case of a REST API, one would:

  • Export an array of routes in user.ts with URL patterns such as /api/users and /api/users/:id.
  • Export an array of routes in products.ts with URL patterns such as /api/products and /api/products/:id.
  • Import these in main.ts, then call Deno.serve(route([...userRoutes, ...productRoutes, notFoundRoute], errorHandler)).

The current defaultHandler() does not seem very useful, as a wildcard route can provide the same functionality (see tests). I believe an optional errorHandler() would be more important.

While my PR adds some logic to the route() function, it conforms to the relevant specifications (RFC2616) and practices regarding the "Method Not Allowed" response, error handling, and the default "Not Found" response, at least to my understanding. Furthermore, all of the new default behavior remains customizable by the user.

Accepting this PR in its current form would essentially mean that the URLPattern would be the only factor determining whether a Route can handle the request or not.

@kerezsiz42 kerezsiz42 requested a review from kt3k as a code owner December 25, 2024 10:18
@CLAassistant
Copy link

CLAassistant commented Dec 25, 2024

CLA assistant check
All committers have signed the CLA.

@github-actions github-actions bot added the http label Dec 25, 2024
Copy link

codecov bot commented Dec 25, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 96.34%. Comparing base (c40f593) to head (6f1d3e6).

Additional details and impacted files
@@           Coverage Diff           @@
##             main    #6305   +/-   ##
=======================================
  Coverage   96.33%   96.34%           
=======================================
  Files         547      547           
  Lines       41667    41681   +14     
  Branches     6314     6316    +2     
=======================================
+ Hits        40140    40157   +17     
+ Misses       1484     1482    -2     
+ Partials       43       42    -1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@kerezsiz42 kerezsiz42 changed the title feat(http/route): add capability to attach handlers by methods, implement sensible defaults feat(http/unstable): add capability to attach handlers by methods, implement sensible defaults Dec 25, 2024
@kt3k kt3k changed the title feat(http/unstable): add capability to attach handlers by methods, implement sensible defaults BREAKING(http/unstable): add capability to attach handlers by methods, implement sensible defaults Dec 31, 2024
}
}
return defaultHandler(request, info);

return new Response("Not Found", { status: 404 });
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it's a good idea to remove the capability to customize the 404 page

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I mentioned it in the PR but did not emphasize it enough. So putting a wildcard route that matches any URLPattern at the end of the Route[] achieves exactly the same result as the current defaultHandler:

const wildcardRoute: Route = {
  pattern: new URLPattern({ pathname: "/*" }),
  handler: (request: Request) => {
    return new Response(new URL(request.url).pathname, { status: 404 });
  },
};

For this reason I think that the defaultHandler is unnecessary, and the second parameter of route could be deleted or changed to something else without losing features.

@kt3k
Copy link
Member

kt3k commented Dec 31, 2024

Thanks for the suggestion.

The addition of errorHandler option seems interesting to me. But we probably don't need the default implementation as Deno.serve already has default error handling which returns the equivalent of new Response("Internal Server Error", { status: 500 }).

I would like to propose a new implementation of the route() function that adds the capability to define handlers on a per-method basis (in a style similar to Fresh) or to use a single handler that handles all methods.

I don't see much benefit of this change. This design seems rather confusing to me as handler and handlers are similar in names, but have different effects.

@kerezsiz42
Copy link
Author

Thanks for the suggestion.

The addition of errorHandler option seems interesting to me. But we probably don't need the default implementation as Deno.serve already has default error handling which returns the equivalent of new Response("Internal Server Error", { status: 500 }).

I would like to propose a new implementation of the route() function that adds the capability to define handlers on a per-method basis (in a style similar to Fresh) or to use a single handler that handles all methods.

I don't see much benefit of this change. This design seems rather confusing to me as handler and handlers are similar in names, but have different effects.

Thanks for the code review!

You did not criticize what I thought you would. So if I understand you correctly, only the naming of handler and handlers is problematic, and you don't like the redundancy that the errorHandler() parameter's default value provides. How should they be named in your opinion? If I remove the default value of errorHandler(), will it be acceptable?

I understand that this module of the std library is not on agenda currently, but we, as library developers should be concentrating on what the users of the standard library want. And a high quality HTTP toolkit is of utmost importance as we see it in case of Go. For new JS/TS projects the default option for new users should be @std/http, so we should strive to be better in ergonomics and ease of use compared to Hono, Oak and others while keeping the solution as bare-bones as possible.

I am new to open source development, so I might not be familiar with how this kind of development really works. I am keen to hearing your advice and opinion!

@kerezsiz42 kerezsiz42 requested a review from kt3k January 16, 2025 16:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants